package com.demo.word;

import com.alibaba.fastjson2.JSON;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.*;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * pom 中必须引入 poi-scratchpad 依赖
 */
public class HwpfTest {
  
   @Test
   public void testReadByDoc() throws Exception {
      InputStream is = Files.newInputStream(Paths.get("D:\\test.doc"));
      HWPFDocument doc = new HWPFDocument(is);

      //输出书签信息
//      this.printInfo(doc.getBookmarks());
      //输出文本
      System.out.println(doc.getDocumentText());
      Range range = doc.getRange();
//    this.insertInfo(range);
//      this.printInfo(range);
      //读表格
//      this.readTable(range);
      //读列表
      this.readList(range);
      //删除range
      Range r = new Range(2, 5, doc);
      r.delete();//在内存中进行删除，如果需要保存到文件中需要再把它写回文件
      //把当前HWPFDocument写到输出流中
      // doc.write(Files.newOutputStream(Paths.get("D:\\test.doc")));
      this.closeStream(is);
   }
  
   /**
    * 关闭输入流
    * @param is
    */
   private void closeStream(InputStream is) {
      if (is != null) {
         try {
            is.close();
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
   }
  
   /**
    * 输出书签信息
    */
   private void printInfo(Bookmarks bookmarks) {
      int count = bookmarks.getBookmarksCount();
      System.out.println("书签数量：" + count);
      Bookmark bookmark;
      for (int i=0; i<count; i++) {
         bookmark = bookmarks.getBookmark(i);
         System.out.println("书签" + (i+1) + "的名称是：" + bookmark.getName());
         System.out.println("开始位置：" + bookmark.getStart());
         System.out.println("结束位置：" + bookmark.getEnd());
      }
   }
  
   /**
    * 读表格
    * 每一个回车符代表一个段落，所以对于表格而言，每一个单元格至少包含一个段落，每行结束都是一个段落。
    * @param range
    */
   private void readTable(Range range) {
      // 遍历range范围内的table。
      TableIterator tableIter = new TableIterator(range);
      Table table;
      TableRow row;
      TableCell cell;
      while (tableIter.hasNext()) {
         table = tableIter.next();
         int rowNum = table.numRows();
         System.out.println("read ======================================================= table, rowNum: " + rowNum);
         for (int j=0; j<rowNum; j++) {
            row = table.getRow(j);
            int cellNum = row.numCells();
            StringBuilder rowSb = new StringBuilder();
            for (int k=0; k<cellNum; k++) {
               cell = row.getCell(k);
                // 输出单元格的文本
               rowSb.append(cell.text().trim()).append("\t");
            }
            System.out.println(rowSb);
         }
      }
   }

   @Getter
   @Setter
   public static class ReadList {
      private int tableNum;
      private int level;
      private String title;
   }
  
   /**
    * 读列表
    */
   private void readList(Range range) {
      int num = range.numParagraphs();
      Paragraph para;
      boolean hasTable = false;
      Map<String, ReadList> data = new LinkedHashMap<>();
      String currentParaText = "";
      for (int i=0; i<num; i++) {
         para = range.getParagraph(i);
         if (para.isInList()) {
            if (para.text().contains("\u0007")) {
               continue;
            }
            if (StringUtils.isEmpty(currentParaText)) {
               currentParaText = para.text()
                       .replace("\r\n", "").replace("\r", "");
            }
            if (hasTable) {
               ReadList readList = data.computeIfAbsent(currentParaText, v -> new ReadList());
               readList.setTableNum(readList.getTableNum() + 1);
               hasTable = false;
            }

            currentParaText = para.text().replace("\r\n", "").replace("\r", "");
            ReadList readList = data.computeIfAbsent(currentParaText, v -> new ReadList());
            readList.setLevel(para.getIlvl());
            readList.setTitle(currentParaText);
//            System.out.println("list: " + para.getIlvl() + ":" + para.text());
         }
         if (para.isInTable()) {
            hasTable = true;
         }
      }
      // 处理最后一个目录下的表
      if (hasTable) {
         ReadList readList = data.computeIfAbsent(currentParaText, v -> new ReadList());
         readList.setTableNum(readList.getTableNum() + 1);
      }
      data.forEach((k, v) -> {
         System.out.println(JSON.toJSONString(v));
      });
   }
  
   /**
    * 输出Range
    */
   private void printInfo(Range range) {
      //获取段落数
      int paraNum = range.numParagraphs();
      System.out.println(paraNum);
      for (int i=0; i<paraNum; i++) {
         if (!range.getParagraph(i).isInTable()) {
            System.out.println("段落" + (i+1) + "：" + range.getParagraph(i).text());
         }
//       this.insertInfo(range.getParagraph(i));

         if (i == (paraNum-1)) {
            // this.insertInfo(range.getParagraph(i));
         }
      }
      int secNum = range.numSections();
//      System.out.println(secNum);
      Section section;
      for (int i=0; i<secNum; i++) {
         section = range.getSection(i);
//         System.out.println(section.getMarginLeft());
//         System.out.println(section.getMarginRight());
//         System.out.println(section.getMarginTop());
//         System.out.println(section.getMarginBottom());
//         System.out.println(section.getPageHeight());
//         System.out.println(section.text());
      }
   }
  
   /**
    * 插入内容到Range，这里只会写到内存中
    */
   private void insertInfo(Range range) {
      range.insertAfter("Hello");
   }
  
}